#pragma once

#include <iostream>
#include <string>
#include "Sock.hpp"
#include <poll.h>
#include <system_error>
#include <vector>
#include <algorithm>
#include <functional>

namespace poll_ns
{

    const int default_port = 8080;
    const int default_fd_size = 1024;
    const int default_fd = -1;

    using func_t = std::function<std::string(const std::string &)>;

    class PollServer
    {
    public:
        PollServer(func_t func, int port = default_port)
            : _port(port), _listensock(-1), _rfds(nullptr), _func(func)
        {
        }

        ~PollServer()
        {
            if (_listensock > 0)
                close(_listensock);

            if (_rfds)
                delete[] _rfds;
        }

        void Accepter();
        void Recver(int pos);

        void ResetFD(struct pollfd& rfd)
        {
            rfd.fd = default_fd;
            rfd.events = 0;
            rfd.revents = 0;
        }

        void HandlerEvent()
        {

            // 若有多个文件描述符就绪，处理已经就绪的文件描述符
            for (int pos = 0; pos < default_fd_size; ++pos)
            {
                // 过滤非法fd
                if (_rfds[pos].fd == default_fd)
                    continue;

                if (_rfds[pos].events & POLLIN)
                {
                    if (_rfds[pos].fd == _listensock && (_rfds[pos].revents & POLLIN)) // 如果监听事件就绪
                    {
                        Accepter();
                    }
                    else if (_rfds[pos].revents & POLLIN) // 如果其他事件就绪
                    {
                        Recver(pos);
                    }
                }
            }
        }

        void initServer()
        {
            _listensock = Sock::Socket();
            Sock::Bind(_listensock, _port);
            Sock::Listen(_listensock);

            _rfds = new struct pollfd[default_fd_size];

            for (int i = 0; i < default_fd_size; ++i)
            {
                ResetFD(_rfds[i]);
            }

            _rfds[0].fd = _listensock;
            _rfds[0].events = POLLIN;
        }

        void start()
        {

            while (true)
            {
                int pollret = poll(_rfds, default_fd_size, -1);

                std::system_error erro(errno, std::generic_category());
                switch (pollret)
                {
                case 0: // 超时返回
                    logMessage(NORMAL, "timeout...");
                    break;
                case -1: // 错误返回
                    logMessage(WARNING, "select err, errCode: %d, %s", erro.code().value(), erro.what());
                    break;
                default:
                    logMessage(NORMAL, "get a new link...");
                    HandlerEvent();
                    break;
                }
            }
        }

    private:
        int _port;
        int _listensock;
        struct pollfd *_rfds;
        func_t _func;
    };

    void PollServer::Accepter()
    {
        std::string clientip;
        uint16_t clientport;
        int sock = Sock::Accept(_listensock, &clientip, &clientport);
        if (sock < 0)
        {
            return;
        }

        // 将用户的 文件描述符 保存
        int i = 0;
        for (i = 0; i < default_fd_size; ++i)
        {
            if (_rfds[i].fd != default_fd)
                continue;
            else
                break;
        }
        if (i == default_fd_size)
        {
            logMessage(WARNING, "server is full, plase wait at time");
            close(sock);
        }
        else // 保存文件描述符
        {
            _rfds[i].fd = sock;
            _rfds[i].events = POLLIN;
            _rfds[i].revents = 0;
        }
    }

    void PollServer::Recver(int pos)
    {
        // 1. 读取报文，保证完整读到一整个报文（暂时不处理
        char buffer[1024];
        ssize_t n = recv(_rfds[pos].fd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0; // 去除换行符
            logMessage(NORMAL, "client # %s", buffer);
        }
        else if (n == 0)
        {
            close(_rfds[pos].fd);
            ResetFD(_rfds[pos]);
            logMessage(NORMAL, "client quit");
            return;
        }
        else
        {
            close(_rfds[pos].fd);
            ResetFD(_rfds[pos]);
            std::system_error erro(errno, std::generic_category());
            logMessage(ERROR, "recverro: %d, %s", erro.code().value(), erro.what());
        }

        // 2. 处理请求 request -> respond
        std::string respond = _func(buffer);

        // 3. send
    }
}